using SqlQueryBuilder.Clauses;
using SqlQueryBuilder.Criterias;

namespace SqlQueryBuilder.Queries
{
    /// <summary>
    /// Insert Query
    /// </summary>
    public class InsertQuery : IInsertQuery
    {
        private readonly Insert insertClause;
        private readonly IntoCriteria into;
        private ValuesCriteria values;
        private IInterrogationQuery select;

        /// <summary>
        /// Initializes a new instance of the <see cref="InsertQuery"/> class.
        /// </summary>
        /// <param name="tableName">Name of the table.</param>
        public InsertQuery(string tableName)
        {
            insertClause = new Insert(tableName);
            into = new IntoCriteria();
            values = new ValuesCriteria();
        }

        /// <summary>
        /// Intoes the specified into clauses.
        /// </summary>
        /// <param name="intoClauses">The into clauses.</param>
        /// <returns></returns>
        public IInsertQuery Into(params string[] intoClauses)
        {
            foreach (var intoClause in intoClauses)
            {
                into.intoClauses.Add(intoClause);
            }
            return this;
        }

        /// <summary>
        /// Intoes the specified into clauses.
        /// </summary>
        /// <param name="selectinto">The selectinto.</param>
        /// <returns></returns>
        public IInsertQuery Select(IInterrogationQuery selectinto)
        {
            select = selectinto;
            values = null;
            return this;
        }

        /// <summary>
        /// Valueses the specified value clauses.
        /// </summary>
        /// <param name="valueClauses">The value clauses.</param>
        /// <returns></returns>
        public IInsertQuery Values(params object[] valueClauses)
        {
            foreach (var intoClause in valueClauses)
            {
                values.valueClauses.Add(intoClause);
            }
            select = null;
            return this;
        }

        /// <summary>
        /// Valueses the specified insert clauses.
        /// </summary>
        /// <param name="insertClauses">The insert clauses.</param>
        /// <returns></returns>
        public IInsertQuery Values(params InsertClause[] insertClauses)
        {
            foreach (var clause in insertClauses)
            {
                into.intoClauses.Add(clause.Field);
                values.valueClauses.Add(clause.Value);
            }
            return this;
        }

        /// <summary>
        /// Builds the query.
        /// </summary>
        /// <returns></returns>
        public string BuildQuery()
        {
            string data = values != null? values.BuildCriteria(): select.BuildQuery();
            return insertClause.BuildCriteria() +
                   into.BuildCriteria() + data;
        }
    }
}